;ROM - Data Technology Corporation CP/M 2.2 ROM.
;
;	+-----------------------+
;	|			|
;	|    R O M   B O O T 	|
;	|			|
;	+-----------------------+
;
;
;
;	Version number:	2.2D
;	Version date:	March 19, 1981
;
;	Update date:	March 24, 1981
;
;			Boots from logical unit 020h (floppy)
;			if it is ready.  Passes logical unit number
;			to the BOOT routine in the A register.
;
;	Update date:	June 15, 1981
;			Modified to wait three seconds for boot
;			LUN from keyboard.
;
;	The following code is supplied to customers who
;	purchase a hard/floppy disk system from DTC.
;	The following code is written onto track 0 sector 0
;	of the hard disk.  This routine is read into memory
;	at location 0 by the user's PROM.   This routine then
;	loads the rest of the system into memory.
;
;
;	The format of the Hard Disk Boot sectors are as follows:
;
;	Logical		Routine
;	Sector		Name
;
;	  0		Boot program
;
;	1 thru 8	CCP
;
;	9 thru 22	BDOS
;
;	23 thru 32	DTC CBIOS
;
;


VERS:	EQU	22


FWA:	EQU	800H - 20H
BTFWA:	EQU	0100h






	ORG	FWA
	JMP	START-FWA

START:	LXI	B,0800h
	LXI	H,FWA+0800h

START1:	DCX	H
	DCX	B
	LDAX	B
	MOV	M,A
	MOV	A,C
	ORA	B
	JNZ	START1-FWA
	JMP	BOOT

;
;
	ORG	FWA + 20H

BOOT:
	IF	I696
	MVI	A,1
	OUT	0FDh		;disable rom

CNIN:	EQU	0		;Console input port
CONSTS:	EQU	1		;Console status port

RBR:	EQU	2		;Input status mask
	ENDIF

	IF	I796
	MVI	A,80h
	OUT	0EBh		;disable rom

CNIN:	EQU	0ECh		;Console input port
CONSTS:	EQU	0EDh		;Console status port

RBR:	EQU	2		;Input status mask

PIT:	EQU	0DEh		;Programmable interval timer

;	Initialize console
	MVI	A,0B6h		;Set PIT for 9600 baud
	OUT	PIT+1
	MVI	A,8
	OUT	PIT+0
	MVI	A,0
	OUT	PIT+0
	MVI	A,04Eh		;Setup serial port
	OUT	CONSTS
	MVI	A,037h
	OUT	CONSTS
	IN	CNIN
	ENDIF

	LXI	SP,STACK
;
	LXI	B,3000		;wait 3 seconds
	CALL	DELAY
	IN	CONSTS
	ANI	RBR
	JZ	BOOTA		;if no character
	IN	CNIN		;Get character pressed
	SUI	'0'
	JM	BOOTA
	CPI	4
	JNC	BOOTA
	RRC
	RRC
	RRC
	STA	LUN
BOOTA:
	LXI	D,BTFWA
	LXI	H,CIOPB
	CALL	RDISK
	ORA	A
	JNZ	BOOTA
	MOV	A,C
	ANI	FERR
	JNZ	BOOTA
	LDA	LUN
	JMP	BTFWA
;
;
;
CIOPB:	DB	RDCMD
LUN:	DB	0
	DW	0		;Read logical sec 0
	DB	2		;2 sectors in case of floppy
	DB	0		;Perform retries
;	Delay a period of time
;	Enter:	BC no. of milliseconds to delay

DELCNT:	EQU	4*1000 		;4 Mhz

DELAY:	MVI	A,DELCNT/26
DLAY1:	INX	B
	DCX	B
	DCR	A
	JNZ	DLAY1
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	DELAY
	RET

;	Disk I/O Routines
;
;
	IF	I696
;	E X E C

EXEC:	MVI	B,BUSY		;Wait for not busy.
	MVI	C,BUSY and (not BUSY)
	CALL	WAITM
	RNZ
	

	MVI	A,SLCT		;Alert controller
	OUT	DIO+1
EXEC1:
	MOV	C,B		;Wait for controller busy
	CALL	WAITM
	RNZ

	MVI	A,DODTA		;Enable data in
	OUT	DIO+1

EXEC2:	IN	DIO+2		;Get status
	XRI	0FFh
	JM	EXEC2		;If not requesting next byte
	ANI	CMND+DIROUT
	JNZ	EXEC3		;If CMND or DIROUT false
	MOV	A,M
	INX	H
	OUT	DIO		;Send byte from command buffer
	JMP	EXEC2

EXEC3:	CMP	A		;Z:=1
	RET
;
;
;
;
;	WDISK - Output from memory buffer.
;	ENTRY:	HL = COMMAND BUFFER ADDRESS
;		DE = DATA BUFFER ADDRESS
;

WDISK:	CALL	EXEC		;Output command
	RNZ			;Return if timeout
WDISK1:	IN	DIO+2		;Read status
	ORA	A
	JP	WDISK1		;If request is present
	ANI	CMND
	JNZ	GCMPS		;If done with transfer
	LDAX	D		;Get the data byte
	OUT	DIO
	INX	D		;Advance buffer address
	JMP	WDISK1
;
;
;
;
;	RDISK - Input to memory buffer.
;
;	Entry:	HL = command buffer address
;		DE = data buffer address

RDISK:	CALL	EXEC
	RNZ			;Return if timeout
RDISK1:	IN	DIO+2		;Read status
	ORA	A
	JP	RDISK1		;If request is present
	ANI	CMND
	JNZ	GCMPS
	IN	DIO
	STAX	D
	INX	D
	JMP	RDISK1
;
;
;
;
;	WAITF - Wait for function to complete.

WAITF:	MVI	B,REQ+CMND	;Wait for both REQ and CMND
	MOV	C,B
	CALL	WAITM
	RNZ
;
;	Get completion status.

GCMPS:	IN	DIO		;Get completion status
	MOV	C,A

GCMP1:	IN	DIO+2
	ORA	A
	JP	GCMP1		;If REQ not set

	MOV	B,A
	IN	DIO		;Get message byte
	RET
	ENDIF
;

;
;
;
	IF	I796
;	EXEC - Output the command
;
;	Enter:	HL is the command buffer address
;		DE - data transfer address.

EXEC:
	MOV	A,E		;Output DMA address
	OUT	DIO+2
	MOV	A,D
	OUT	DIO+3
	MOV	A,L
	OUT	DIO+4
	MOV	A,H
	OUT	DIO+5
	MVI	A,0
	OUT	DIO+6
	OUT	DIO+7
	OUT	DIO
	CMP	A		;Z:=1
	RET


;	Disk read/write
;
;	Entry:	same as EXEC
;
RDISK:
WDISK:	CALL	EXEC
	RNZ			;Return if timeout

;	WAITF - Wait until transfer done
;
;	Enter:	none
;	Exit:	when transfer completed

WAITF:	MVI	B,CMDDON	;Wait for CMDDON
	MOV	C,B
	CALL	WAITM
	RNZ			;Return if timeout
;

;	GCMPS - Get completion status
;
;	Enter:	none
;	Exit:	Status in C
GCMPS:	IN	DIO+1
	MOV	C,A
	RET
	ENDIF

;	WAITM - Wait for controller with timeout
;
;	Entry:	B=Status mask
;		C=Status value
;	Exit:	Z=1 if OK, else timeout with A=C=TERR
;
WAITM:
	PUSH	D		;Save D
	PUSH	H
	LXI	H,138		;Two minute timeout
	LXI	D,0		;Max wait @4MHZ is 868 ms
WAITML:
	IF	I696
	IN	DIO+2
	ENDIF
	IF	I796
	IN	DIO
	ENDIF
	ANA	B		;Mask wait bits
	CMP	C		;Check value
	JZ	WAITM1
	DCX	D		;Not ready.  Decrement time
	MOV	A,D
	ORA	E
	JNZ	WAITML
	DCX	H
	MOV	A,H
	ORA	L
	JNZ	WAITML
	MVI	B,0		;Timeout
	MVI	A,TERR
	ORA	A
WAITM1:
	POP	H
	POP	D		;Restore D
	MOV	C,A		;Return status in C
	RET
;
	ORG	FWA + 200H
STACK:
	END
